package controller;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;

import modele.Square;
import modele.World;
import modele.WorldElem.Burning;
import modele.WorldElem.Earth;
import modele.WorldElem.Grass;
import modele.WorldElem.None;
import modele.WorldElem.Rock;
import modele.WorldElem.Sand;
import modele.WorldElem.SecondaryState;
import modele.WorldElem.State;
import modele.WorldElem.Tree;
import modele.WorldElem.WaterSource;

public class FirePropagationRule1 extends Rule {
	
	public FirePropagationRule1(World w) {
		super(w);
	}

	/**
	 * "Earth" n'est pas un élément inflammable donc il ne peut prendre feu.
	 */
	@Override
	public void applyRule(Earth e, Square s) {
		if(s.getSecondaryStateValue() == SecondaryState.BURNING){
			s.setSecondaryState(new None());
		}
		else getEvolvedSquareMap()[s.getPosX()][s.getPosY()]=null;

	}

	/**
	 * "Grass" est un élément qui peut subir les dégats du feu.
	 * Si un feu est présent dans une case proche de grass celle-ci
	 * se transforme en Earth.
	 */
	@Override
	public void applyRule(Grass g, Square s) {
		//on récupére les cases du vrai world (pas les cases tampon pour éviter de tout enflammer
		//d'un coup.
		Square sWorld = getWorld().getSquareMap()[s.getPosX()][s.getPosY()];
		ArrayList<ArrayList<Square>> squares = sWorld.getSquareAround(getWorld(), 1);
		Random r = new Random();
		int nbBurningState = getNbBurningState(squares);
		if(sWorld.getSecondaryStateValue() != SecondaryState.BURNING){
			if(nbBurningState > 0){
				//on enflamme l'herbe
				if(r.nextFloat() < 0.2 * (float)nbBurningState){
					s.setSecondaryState(new Burning());
				}
			}
			else if (r.nextDouble() < 1.0/((double)30.0*(Math.pow(getWorld().getWidth(), 2)))){
				s.setSecondaryState(new Burning());
			}
			else getEvolvedSquareMap()[s.getPosX()][s.getPosY()]=null;
		}
		else{
			if(((Burning)sWorld.getSecondaryState()).getBurningTime() >= 1){
				//l'herbe ne reste enflammé que 1 tour.
				s.setState(new Earth());
				s.setSecondaryState(new None());
			}
		}
		
	}

	@Override
	public void applyRule(Rock r, Square s) {
		if(s.getSecondaryStateValue() == SecondaryState.BURNING){
			s.setSecondaryState(new None());
		}
		else getEvolvedSquareMap()[s.getPosX()][s.getPosY()]=null;
	}

	@Override
	public void applyRule(Sand sa, Square s) {
		if(s.getSecondaryStateValue() == SecondaryState.BURNING){
			s.setSecondaryState(new None());
		}
		else getEvolvedSquareMap()[s.getPosX()][s.getPosY()]=null;

	}

	@Override
	public void applyRule(Tree t, Square s) {
		//on récupére les cases du vrai world (pas les cases tampon pour éviter de tout enflammer
		//d'un coup.
		Square sWorld = getWorld().getSquareMap()[s.getPosX()][s.getPosY()];
		ArrayList<ArrayList<Square>> squares = sWorld.getSquareAround(getWorld(), 1);
		Random r = new Random();
		int nbBurningState = getNbBurningState(squares);
		if(sWorld.getSecondaryStateValue() != SecondaryState.BURNING){
			if(nbBurningState > 0){
				//on enflamme l'arbre
				if(r.nextFloat() < 0.3 * (float)nbBurningState){
					s.setSecondaryState(new Burning());
				}
			}
			else if (r.nextDouble() < 1.0/((double)30.0*(Math.pow(getWorld().getWidth(), 2)))){
				s.setSecondaryState(new Burning());
			}
			else getEvolvedSquareMap()[s.getPosX()][s.getPosY()]=null;
		}
		else{ 
			((Burning)s.getSecondaryState()).setBurningTime(((Burning)sWorld.getSecondaryState()).getBurningTime()+1);
			//Un arbre met 5 tours à s'éteindre.
			if(((Burning)sWorld.getSecondaryState()).getBurningTime() >= 5){
				s.setState(new Earth());
				s.setSecondaryState(new None());
			}
		}
	}
	
	
	

	@Override
	public void applyRule(WaterSource ws, Square s) {
		if(s.getSecondaryStateValue() == SecondaryState.BURNING){
			s.setSecondaryState(new None());
		}
		else getEvolvedSquareMap()[s.getPosX()][s.getPosY()]=null;
	}
	
	
	
	private int getNbBurningState(ArrayList<ArrayList<Square>> squares){
		//On compte le nombre de case brulant à coté.
		Iterator<ArrayList<Square>> itArray = squares.iterator();
		int nbBurningState = 0;
		while(itArray.hasNext()){
			Iterator<Square> itSquare = itArray.next().iterator();
			while(itSquare.hasNext()){
				Square tmp = itSquare.next();
				if(tmp.getSecondaryStateValue() == SecondaryState.BURNING){
					nbBurningState++;
				}
			}
		}
		return nbBurningState;
	}

	@Override
	public void prepareToEvolve() {
		setEvolvedSquareMap(getWorld().cloneSquareMap());
	}

	@Override
	public int getRuleValue() {
		return FIREPROPAGATION1;
	}


}
